package com.kyk.filter;

import com.kyk.util.JwtUtils;
import io.jsonwebtoken.Claims;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.core.Ordered;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;
import java.util.Arrays;
import java.util.List;

/**
 * 网关JWT全局过滤器（严格实现GlobalFilter和Ordered接口）
 */
@Component // 注入Spring容器，全局生效
public class JwtAuthGlobalFilter implements GlobalFilter, Ordered {

    @Autowired
    private JwtUtils jwtUtils; // 注入JWT工具类，直接调用其方法

    // 不需要验证的路径（登录、注册等公开接口）
    private static final List<String> EXCLUDE_PATHS = Arrays.asList(
            "/users/login/**",
            "/users/registerSendCode/**",
            "/users/resetSendCode/**",
            "/users",
            "/upload/**",
            "/merchants/login/**",
            "/merchants",
            "/admin/login/**"
    );

    private final AntPathMatcher pathMatcher = new AntPathMatcher(); // 支持Ant风格路径匹配

    /**
     * 核心过滤逻辑（实现GlobalFilter接口的方法）
     */
    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        String path = request.getPath().value();

        // 1. 公开接口直接放行（调用JwtUtils之外的路径匹配逻辑）
        if (isExcludedPath(path)) {
            return chain.filter(exchange);
        }

        // 2. 从请求头获取令牌（格式：Authorization: Bearer <token>）
        String token = extractToken(request);
        if (token == null) {
            return handleError(exchange, HttpStatus.UNAUTHORIZED, "未提供有效的令牌");
        }

        // 3. 调用JwtUtils验证令牌有效性
        // 先获取验证结果（Claims对象）
        Claims claims = jwtUtils.validateToken(token);
            // 如果返回null，说明令牌无效或已过期
        if (claims == null) {
            return handleError(exchange, HttpStatus.UNAUTHORIZED, "令牌无效或已过期");
        }

        // 4. 调用JwtUtils提取用户信息（用户ID和类型）
        Long userId = jwtUtils.getUserIdFromToken(token);
        String userType = jwtUtils.getUserTypeFromToken(token);
        if (userId == null || userType == null) {
            return handleError(exchange, HttpStatus.UNAUTHORIZED, "令牌信息不完整");
        }

        // 5. 验证用户类型与路径是否匹配（三端隔离）
        if (!isUserTypeMatchPath(userType, path)) {
            return handleError(exchange, HttpStatus.FORBIDDEN, "无权访问此接口");
        }

        // 6. 将用户信息存入请求头，传递给下游服务
        ServerHttpRequest mutatedRequest = request.mutate()
                .header("X-User-Id", userId.toString())
                .header("X-User-Type", userType)
                .build();

        // 7. 继续执行过滤器链（转发请求到目标服务）
        return chain.filter(exchange.mutate().request(mutatedRequest).build());
    }

    /**
     * 提取令牌（从Authorization头中）
     */
    private String extractToken(ServerHttpRequest request) {
        String authHeader = request.getHeaders().getFirst("Authorization");
        if (authHeader != null && authHeader.startsWith("Bearer ")) {
            return authHeader.substring(7).trim();
        }
        return null;
    }

    /**
     * 判断路径是否为公开接口
     */
    private boolean isExcludedPath(String path) {
        return EXCLUDE_PATHS.stream()
                .anyMatch(excludedPath -> pathMatcher.match(excludedPath, path));
    }

    /**
     * 验证用户类型与请求路径是否匹配（三端隔离核心逻辑）
     */
    private boolean isUserTypeMatchPath(String userType, String path) {
        if ("USER".equals(userType) && path.startsWith("/users/")) {
            return true;
        } else if ("MERCHANT".equals(userType) && path.startsWith("/merchants/")) {
            return true;
        }else if ("MERCHANT".equals(userType) && path.startsWith("/restaurants")) {
            return true;
        } else if ("ADMIN".equals(userType) && path.startsWith("/admin/")) {
            return true;
        }
        return false;
    }

    /**
     * 处理错误响应（返回JSON格式错误信息）
     */
    private Mono<Void> handleError(ServerWebExchange exchange, HttpStatus status, String message) {
        ServerHttpResponse response = exchange.getResponse();
        response.setStatusCode(status);
        response.getHeaders().add("Content-Type", "application/json;charset=UTF-8");

        String json = String.format("{\"code\":%d,\"message\":\"%s\"}", status.value(), message);
        return response.writeWith(Mono.just(response.bufferFactory().wrap(json.getBytes())));
    }

    /**
     * 指定过滤器执行顺序（实现Ordered接口的方法）
     * 返回值越小，执行优先级越高（确保在路由转发前验证令牌）
     */
    @Override
    public int getOrder() {
        return -100; // 高于路由过滤器的优先级（默认路由过滤器order为0）
    }
}
